#include <iostream>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/features2d/features2d.hpp>

using namespace std;
using namespace cv;

int element_shape = MORPH_RECT;
double PI = 4.0 * atan(1.0);
int imageNumber=0;

void captureCoin(Mat image, RotatedRect elipse) {
	//image should be square
	//width or height length must be odd
	int coinDiameter =
			(int) elipse.size.height > elipse.size.width ? elipse.size.height
					: elipse.size.width;

	int upperCornerX = elipse.center.x - (coinDiameter) / 2;
	int upperCornerY = elipse.center.y - (coinDiameter) / 2;
	if (coinDiameter % 2 == 0) {
		coinDiameter++;
		upperCornerX = elipse.center.x - (coinDiameter - 1) / 2;
		upperCornerY = elipse.center.y - (coinDiameter - 1) / 2;
	}

	Rect roi(upperCornerX,upperCornerY,coinDiameter,coinDiameter);

	Mat coin=image(roi);

	//apply threshold

	String coinNumberStr;
	std::stringstream out;
	out << imageNumber++;
	coinNumberStr = out.str();

	String imageName="coin-"+ coinNumberStr + ".jpg";
	imwrite(imageName,coin);

}

double getCircleMeanStdError(vector<Point> contour, RotatedRect elipse) {
	Point center = elipse.center;
	double radius = (elipse.size.height + elipse.size.width) / 4;
	double mean = 0;
	for (int i = 0; i < contour.size(); i++) {
		double dist = sqrt((contour[i].x - center.x)
				* (contour[i].x - center.x) + (contour[i].y - center.y)
				* (contour[i].y - center.y));
		mean += fabs(dist - radius);
	}

	double meanStd = 0;
	for (int i = 0; i < contour.size(); i++) {
		double dist = sqrt((contour[i].x - center.x)
				* (contour[i].x - center.x) + (contour[i].y - center.y)
				* (contour[i].y - center.y));
		meanStd += (dist - radius) * (dist - radius);
	}

	meanStd = meanStd / contour.size();

	cout << "total error:" << mean;
	mean = mean / contour.size();
	cout << "mean error:" << mean << endl;
	cout << "mean std error:" << meanStd << endl;

	return meanStd;
}

/*int main() {
	Mat
			image =
					imread(
							"/home/diego/monedometro/resources/Monedas/captures/altura0-8.jpg");

	Mat real = image.clone();
	Mat img, gray, laplace, thresh2, sobel, labels, eroded, bw;
	Mat centers(3, 1, CV_32F);
	Mat thresh(image.rows, image.cols, CV_32FC1);
	cvtColor(image, gray, CV_BGR2GRAY);
	Laplacian(gray,laplace,gray.depth(),3);
	Sobel(gray, sobel, gray.depth(), 1, 1);
	imshow("sobel", sobel);
	threshold(sobel, thresh, 20, 255, CV_THRESH_BINARY);
	threshold(laplace, thresh2, 40, 255, CV_THRESH_BINARY);
	imshow("threshold", thresh2);

	//floodFill;l
	floodFill(image, Point(100, 120), cvScalarAll(0), NULL, cvScalarAll(4),
			cvScalarAll(4));

	//Erosion
	int an = 1;
	Mat element = getStructuringElement(element_shape, Size(an * 2 + 1, an * 2
			+ 1), Point(an, an));
	erode(image, eroded, element, Point(-1, -1), 1);

	//get contours
	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy;
	cvtColor(eroded, bw, CV_BGR2GRAY);

	Mat contoursImage = bw.clone();
	Mat dst = Mat::zeros(contoursImage.size(), CV_8UC3);

	findContours(contoursImage, contours, hierarchy, CV_RETR_CCOMP,
			CV_CHAIN_APPROX_SIMPLE);
	drawContours(dst, contours, -1, cvScalarAll(200));

	cout << contours.size() << endl;

	for (int i = 0; i < contours.size(); i++) {
		Mat contour = Mat(contours[i]);
		if (contourArea(contour, false) > 50.0) {
			//set a as the semi-major axis
			RotatedRect elipse = fitEllipse(contour);
			double a = elipse.size.height;
			double b = elipse.size.width;
			if (b > a) {
				a = elipse.size.width;
				b = elipse.size.height;
			}

			//			double eccentricity = sqrt(1 - pow(b / a, 2));
			double radius = a + b / 4.0;

			double meanError = getCircleMeanStdError(contours[i], elipse);
			if (meanError / radius < 0.1) {
				circle(dst, elipse.center, elipse.size.height / 2, cvScalarAll(
						200));
				captureCoin(thresh2, elipse);
			}

			imshow("dst", dst);
		}
	}

	imshow("real", real);
	imshow("imagen", image);
	imshow("bw", bw);
	imshow("contoursImage", contoursImage);
	imshow("eroded", eroded);

	cvWaitKey(0);
}*/
